1 // --------------------------------------------------------------------------------------------------------------------
2 // <copyright file=
"PhotonHandler.cs" company="Exit Games GmbH">
3 // Part of: Photon Unity Networking
4 // </copyright>
5 // --------------------------------------------------------------------------------------------------------------------

6
7 using
System;
8 using
System.Collections;
9 using
ExitGames.Client.Photon;
10 using
UnityEngine;
11
12 using
Hashtable = ExitGames.Client.Photon.Hashtable;
13
14
15 ///
<summary>
16 ///
Internal Monobehaviour that allows Photon to run an Update loop.
17 ///
</summary>
18 internal
class PhotonHandler : Photon.MonoBehaviour, IPhotonPeerListener
19 {
20     
public static PhotonHandler SP;
21
22     
public int updateInterval; // time [ms] between consecutive SendOutgoingCommands calls
23
24     
public int updateIntervalOnSerialize; // time [ms] between consecutive RunViewUpdate calls (sending syncs, etc)
25
26     
private int nextSendTickCount = 0;
27
28     
private int nextSendTickCountOnSerialize = 0;
29
30     
private static bool sendThreadShouldRun;
31     
public static bool AppQuits;
32
33     
public static Type PingImplementation = null;
34
35     
protected void Awake()
36     {
37         
if (SP != null && SP != this && SP.gameObject != null)
38         {
39             GameObject.DestroyImmediate(SP.gameObject);
40         }
41
42         SP =
this;
43         DontDestroyOnLoad(
this.gameObject);
44
45         
this.updateInterval = 1000 / PhotonNetwork.sendRate;
46         
this.updateIntervalOnSerialize = 1000 / PhotonNetwork.sendRateOnSerialize;
47
48         PhotonHandler.StartFallbackSendAckThread();
49     }

50
51     ///
<summary>Called by Unity when the application is closed. Tries to disconnect.</summary>
52     
protected void OnApplicationQuit()
53     {
54         PhotonHandler.AppQuits =
true;
55         PhotonHandler.StopFallbackSendAckThread();
56         PhotonNetwork.Disconnect();
57     }
58
59     
protected void Update()
60     {
61         
if (PhotonNetwork.networkingPeer == null)
62         {
63             Debug.LogError(
"NetworkPeer broke!");
64             
return;
65         }
66
67         
if (PhotonNetwork.connectionStateDetailed == PeerState.PeerCreated || PhotonNetwork.connectionStateDetailed == PeerState.Disconnected || PhotonNetwork.offlineMode)
68         {
69             
return;
70         }
71
72         
// the messageQueue might be paused. in that case a thread will send acknowledgements only. nothing else to do here.
73         
if (!PhotonNetwork.isMessageQueueRunning)
74         {
75             
return;
76         }
77
78         
bool doDispatch = true;
79         
while (PhotonNetwork.isMessageQueueRunning && doDispatch)
80         {
81             
// DispatchIncomingCommands() returns true of it found any command to dispatch (event, result or state change)
82             UnityEngine.Profiling.Profiler.BeginSample(
"DispatchIncomingCommands");
83             doDispatch = PhotonNetwork.networkingPeer.DispatchIncomingCommands();
84             UnityEngine.Profiling.Profiler.EndSample();
85         }
86
87         
int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000); // avoiding Environment.TickCount, which could be negative on long-running platforms
88         
if (PhotonNetwork.isMessageQueueRunning && currentMsSinceStart > this.nextSendTickCountOnSerialize)
89         {
90             PhotonNetwork.networkingPeer.RunViewUpdate();
91             
this.nextSendTickCountOnSerialize = currentMsSinceStart + this.updateIntervalOnSerialize;
92             
this.nextSendTickCount = 0; // immediately send when synchronization code was running
93         }
94
95         currentMsSinceStart = (
int)(Time.realtimeSinceStartup * 1000);
96         
if (currentMsSinceStart > this.nextSendTickCount)
97         {
98             
bool doSend = true;
99             
while (PhotonNetwork.isMessageQueueRunning && doSend)
100             {
101                 
// Send all outgoing commands
102                 UnityEngine.Profiling.Profiler.BeginSample(
"SendOutgoingCommands");
103                 doSend = PhotonNetwork.networkingPeer.SendOutgoingCommands();
104                 UnityEngine.Profiling.Profiler.EndSample();
105             }
106
107             
this.nextSendTickCount = currentMsSinceStart + this.updateInterval;
108         }
109     }

110
111     ///
<summary>Called by Unity after a new level was loaded.</summary>
112     
protected void OnLevelWasLoaded(int level)
113     {
114         PhotonNetwork.networkingPeer.NewSceneLoaded();
115         PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(Application.loadedLevelName);
116     }
117
118     
protected void OnJoinedRoom()
119     {
120         PhotonNetwork.networkingPeer.LoadLevelIfSynced();
121     }
122
123     
protected void OnCreatedRoom()
124     {
125         PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(Application.loadedLevelName);
126     }
127
128     
public static void StartFallbackSendAckThread()
129     {
130         
if (sendThreadShouldRun)
131         {
132             
return;
133         }
134
135         sendThreadShouldRun =
true;
136         SupportClass.CallInBackground(FallbackSendAckThread);
// thread will call this every 100ms until method returns false
137     }
138
139     
public static void StopFallbackSendAckThread()
140     {
141         sendThreadShouldRun =
false;
142     }
143
144     
public static bool FallbackSendAckThread()
145     {
146         
if (sendThreadShouldRun && PhotonNetwork.networkingPeer != null)
147         {
148             PhotonNetwork.networkingPeer.SendAcksOnly();
149         }
150
151         
return sendThreadShouldRun;
152     }
153
154     
#region Implementation of IPhotonPeerListener
155
156     
public void DebugReturn(DebugLevel level, string message)
157     {
158         
if (level == DebugLevel.ERROR)
159         {
160             Debug.LogError(message);
161         }
162         
else if (level == DebugLevel.WARNING)
163         {
164             Debug.LogWarning(message);
165         }
166         
else if (level == DebugLevel.INFO && PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
167         {
168             Debug.Log(message);
169         }
170         
else if (level == DebugLevel.ALL && PhotonNetwork.logLevel == PhotonLogLevel.Full)
171         {
172             Debug.Log(message);
173         }
174     }
175
176     
public void OnOperationResponse(OperationResponse operationResponse)
177     {
178     }
179
180     
public void OnStatusChanged(StatusCode statusCode)
181     {
182     }
183
184     
public void OnEvent(EventData photonEvent)
185     {
186     }
187
188     
#endregion
189
190
191
192     
#region Photon Cloud Ping Evaluation
193
194
195     
private const string PlayerPrefsKey = "PUNCloudBestRegion";
196
197     
internal static CloudRegionCode BestRegionCodeCurrently = CloudRegionCode.none; // default to none
198     
internal static CloudRegionCode BestRegionCodeInPreferences
199     {
200         
get
201         {
202             
string prefsRegionCode = PlayerPrefs.GetString(PlayerPrefsKey, "");
203             
if (!string.IsNullOrEmpty(prefsRegionCode))
204             {
205                 CloudRegionCode loadedRegion = Region.Parse(prefsRegionCode);
206                 
return loadedRegion;
207             }
208
209             
return CloudRegionCode.none;
210         }
211         
set
212         {
213             
if (value == CloudRegionCode.none)
214             {
215                 PlayerPrefs.DeleteKey(PlayerPrefsKey);
216             }
217             
else
218             {
219                 PlayerPrefs.SetString(PlayerPrefsKey,
value.ToString());
220             }
221         }
222     }
223
224
225
226     
internal protected static void PingAvailableRegionsAndConnectToBest()
227     {
228         SP.StartCoroutine(SP.PingAvailableRegionsCoroutine(
true));
229     }
230
231
232     
internal IEnumerator PingAvailableRegionsCoroutine(bool connectToBest)
233     {
234         BestRegionCodeCurrently = CloudRegionCode.none;
235         
while (PhotonNetwork.networkingPeer.AvailableRegions == null)
236         {
237             
if (PhotonNetwork.connectionStateDetailed != PeerState.ConnectingToNameServer && PhotonNetwork.connectionStateDetailed != PeerState.ConnectedToNameServer)
238             {
239                 Debug.LogError(
"Call ConnectToNameServer to ping available regions.");
240                 
yield break; // break if we don't connect to the nameserver at all
241             }
242
243             Debug.Log(
"Waiting for AvailableRegions. State: " + PhotonNetwork.connectionStateDetailed + " Server: " + PhotonNetwork.Server + " PhotonNetwork.networkingPeer.AvailableRegions " + (PhotonNetwork.networkingPeer.AvailableRegions != null));
244             
yield return new WaitForSeconds(0.25f); // wait until pinging finished (offline mode won't ping)
245         }
246
247         
if (PhotonNetwork.networkingPeer.AvailableRegions == null || PhotonNetwork.networkingPeer.AvailableRegions.Count == 0)
248         {
249             Debug.LogError(
"No regions available. Are you sure your appid is valid and setup?");
250             
yield break; // break if we don't get regions at all
251         }
252
253         
//#if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_IPHONE)
254         
//#pragma warning disable 0162 // the library variant defines if we should use PUN's SocketUdp variant (at all)
255         
//if (PhotonPeer.NoSocket)
256         
//{
257         
// if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
258         
// {
259         
// Debug.Log("PUN disconnects to re-use native sockets for pining servers and to find the best.");
260         
// }
261         
// PhotonNetwork.Disconnect();
262         
//}
263         
//#pragma warning restore 0162
264         
//#endif
265
266         PhotonPingManager pingManager =
new PhotonPingManager();
267         
foreach (Region region in PhotonNetwork.networkingPeer.AvailableRegions)
268         {
269             SP.StartCoroutine(pingManager.PingSocket(region));
270         }
271
272         
while (!pingManager.Done)
273         {
274             
yield return new WaitForSeconds(0.1f); // wait until pinging finished (offline mode won't ping)
275         }
276
277
278         Region best = pingManager.BestRegion;
279         PhotonHandler.BestRegionCodeCurrently = best.Code;
280         PhotonHandler.BestRegionCodeInPreferences = best.Code;
281
282         Debug.Log(
"Found best region: " + best.Code + " ping: " + best.Ping + ". Calling ConnectToRegionMaster() is: " + connectToBest);
283
284
285         
if (connectToBest)
286         {
287             PhotonNetwork.networkingPeer.ConnectToRegionMaster(best.Code);
288         }
289     }
290
291
292
293     
#endregion
294
295 }


--------------------------------------------------------------------------------------------------------------------

Part of: Photon Unity Networking

--------------------------------------------------------------------------------------------------------------------

Internal Monobehaviour that allows Photon to run an Update loop.

public int updateInterval; time [ms] between consecutive SendOutgoingCommands calls

public int updateIntervalOnSerialize; time [ms] between consecutive RunViewUpdate calls (sending syncs, etc)

Called by Unity when the application is closed. Tries to disconnect.

the messageQueue might be paused. in that case a thread will send acknowledgements only. nothing else to do here.

DispatchIncomingCommands() returns true of it found any command to dispatch (event, result or state change)

int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000); avoiding Environment.TickCount, which could be negative on long-running platforms

this.nextSendTickCount = 0; immediately send when synchronization code was running

Send all outgoing commands

Called by Unity after a new level was loaded.

SupportClass.CallInBackground(FallbackSendAckThread); thread will call this every 100ms until method returns false

internal static CloudRegionCode BestRegionCodeCurrently = CloudRegionCode.none; default to none

yield break; break if we don't connect to the nameserver at all

yield return new WaitForSeconds(0.25f); wait until pinging finished (offline mode won't ping)

yield break; break if we don't get regions at all

#if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_IPHONE)

#pragma warning disable 0162 the library variant defines if we should use PUN's SocketUdp variant (at all)

if (PhotonPeer.NoSocket)

{

if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)

{

Debug.Log("PUN disconnects to re-use native sockets for pining servers and to find the best.");

}

PhotonNetwork.Disconnect();

}

#pragma warning restore 0162

#endif

yield return new WaitForSeconds(0.1f); wait until pinging finished (offline mode won't ping)




Trò chơi Tic-Tac-Toe, game đánh caro full source code 53.533 lượt xem

Gõ tìm kiếm nhanh...